﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace 线程池
{
    class Program
    {
        delegate string MyDelegate(string name, int id);
        //http://www.cnblogs.com/kissdodog/archive/2013/03/28/2986026.html


        static void Main(string[] args)
        {
            //通过QueueUserWorkItem启动工作者线程
            // QueueUserWorkItem();
            // 用委托的方式，带参数返回值的方式 BeginInvoke与EndInvoke委托异步调用线程
            //  DelegateWorkItem();
            //IAsyncResult轮询
            //  AsyncResults();
            //IAsyncResult回调函数
            AsyncResultsCallBack();


            Console.ReadKey();
        }
      



        static void QueueUserWorkItem()
        {
            Console.WriteLine("调用线程开始");
            ThreadPool.QueueUserWorkItem(new WaitCallback(workThread1), new P() {  name="sb"});
            Console.WriteLine("不等待线程");
        }
        static void DelegateWorkItem()
        {
            MyDelegate my = new MyDelegate(workDetegate);
            IAsyncResult result = my.BeginInvoke("滇西",2,null,null); //IAsynResult还能轮询判断
            Console.WriteLine("主线程继续工作!");

            //调用EndInvoke(IAsyncResult)获取运行结果，一旦调用了EndInvoke，即使结果还没来得及返回，主线程也阻塞等待了
            //注意获取返回值的方式
            string data = my.EndInvoke(result);
            Console.WriteLine("EndInvoke 调用完了");
            Console.WriteLine(data);
        }
        static void AsyncResults()
        {
            //IAsyncResults 接口属性
            //object AsyncState { get; }       //获取用户定义的对象，它限定或包含关于异步操作的信息。
            //WailHandle AsyncWaitHandle { get; }  //获取用于等待异步操作完成的 WaitHandle。
            //bool CompletedSynchronously { get; } //获取异步操作是否同步完成的指示。
            //bool IsCompleted { get; } 　　　　　　 //获取异步操作是否已完成的指示。

            MyDelegate my = new MyDelegate(workDetegate);
            IAsyncResult result = my.BeginInvoke("滇西", 2, null, null); //IAsynResult还能轮询判断
            Console.WriteLine("主线程继续工作!");
            //AsyncWaitHandle
            //•WaitOne：判断单个异步线程是否完成；
            //•WaitAny：判断是否异步线程是否有指定数量个已完成；
            //•WaitAll：判断是否所有的异步线程已完成；



            while (!result.IsCompleted)
            {
                Thread.Sleep(500);
                Console.WriteLine("异步线程还没完成，主线程干其他事!");
            }

            //while (!result.AsyncWaitHandle.WaitOne(200))
            //{
            //    Console.WriteLine("异步线程没完，主线程继续干活！");
            //}


            string data = my.EndInvoke(result);
            Console.WriteLine(data);
        }
        static void AsyncResultsCallBack()
        {
            MyDelegate my = new MyDelegate(workDetegate);
            IAsyncResult result = my.BeginInvoke("滇西", 2, new AsyncCallback(Completed), new P() { id=100,name="222222222222" });

            //IAsyncResult result = my.BeginInvoke("滇西", 2, new AsyncCallback(x=> {
            //    //获取委托对象，调用EndInvoke方法获取运行结果
            //    AsyncResult _result = (AsyncResult)x;
            //    MyDelegate myDelegaate = (MyDelegate)_result.AsyncDelegate;
            //    //获得参数
            //    string data = myDelegaate.EndInvoke(_result);
            //    Console.WriteLine(data);
            //    //异步线程执行完毕
            //    Console.WriteLine("异步线程完成咯！");
            //    Console.WriteLine("回调函数也是由" + Thread.CurrentThread.Name + "调用的！");

            //}), null);

            // 1.回调函数依然是在辅助线程中执行的，这样就不会影响主线程的运行。
            //2.线程池的线程默认是后台线程。但是如果主线程比辅助线程优先完成，那么程序已经卸载，回调函数未必会执行。如果不希望丢失回调函数中的操作，要么把异步线程设为前台线程，要么确保主线程将比辅助线程迟完成。

        }



        static string workDetegate(string name,int id)
        {
            Console.WriteLine("我是不是线程池线程" + Thread.CurrentThread.IsThreadPoolThread);
            Thread.Sleep(2000);
            return $"{id}-------{name}";



        }
        static void workThread1(object obj)
        {
            Thread.Sleep(2000);
            Console.WriteLine("线程池线程开始!");

            P p = obj as P;
            Console.WriteLine(p.name);

        }

        //供异步线程完成回调的方法
        static void Completed(IAsyncResult result)
        {
            //获取委托对象，调用EndInvoke方法获取运行结果
            AsyncResult _result = (AsyncResult)result;
            MyDelegate myDelegaate = (MyDelegate)_result.AsyncDelegate;
            //获得参数
            string data = myDelegaate.EndInvoke(_result);
            Console.WriteLine(data);

            P p = result.AsyncState as P;
            Console.WriteLine("传过来的参数是：" + p.name);
            //异步线程执行完毕
            Console.WriteLine("异步线程完成咯！");
            Console.WriteLine("回调函数也是由" + Thread.CurrentThread.Name + "调用的！");
        }

    }



    public class P
    {
        public int id { get; set; }

        public string name { get; set; }
    }

}
